#include <stdio.h>
#include <limits.h>

#define V 4 // 图中的顶点数

// 一个实用函数，用于找出距离集合中距离最小的顶点，从未处理的顶点集sptSet[]中
int minDistance(int dist[], int sptSet[]) {
    int min = INT_MAX, min_index;

    for (int v = 0; v < V; v++)
        if (sptSet[v] == 0 && dist[v] <= min)
            min = dist[v], min_index = v;

    return min_index;
}

// 一个实用函数，用于打印构造的距离数组
void printSolution(int dist[]) {
    printf("Vertex \t Distance from Source\n");
    for (int i = 0; i < V; i++)
        printf("%d \t %d\n", i, dist[i]);
}

// 实现Dijkstra算法的函数，使用邻接矩阵表示的图
void dijkstra(int graph[V][V], int src) {
    int dist[V]; // 输出数组。dist[i]将保存源到顶点i的最短距离
    int sptSet[V]; // sptSet[i]为真如果顶点i包含在最短路径树中或最短距离从源到i是最终确定的

    // 初始化所有距离为无穷大，并标记所有顶点未处理
    for (int i = 0; i < V; i++)
        dist[i] = INT_MAX, sptSet[i] = 0;

    // 源顶点到自身的距离总是0
    dist[src] = 0;

    // 找到所有顶点的最短路径
    for (int count = 0; count < V - 1; count++) {
        // 选出一个最小距离顶点从集合未处理的顶点。u总是等于src在第一次迭代
        int u = minDistance(dist, sptSet);

        // 标记这个顶点为已处理
        sptSet[u] = 1;

        // 更新相邻顶点的距离值
        for (int v = 0; v < V; v++)
            if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX 
                && dist[u] + graph[u][v] < dist[v])
                dist[v] = dist[u] + graph[u][v];
    }

    // 打印最终的结果
    printSolution(dist);
}

// 主函数
int main() {
    int graph[V][V] = {{0, 2, 3,4},
                        {1,0,3,0},
                        {1,2,0,4},
                        {0,0,3,0}
                      };

    dijkstra(graph, 0);

    return 0;
}
